package com.example.webview_test.h5_record;

import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.ClientCertRequest;
import android.webkit.HttpAuthHandler;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.SafeBrowsingResponse;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.annotation.Nullable;

/**
 * @Description
 * @Author xudan
 * @CreateTime 2024/4/27
 */
public class MyWebViewClient extends WebViewClient {
    /**
     * 当URL即将在当前WebView中加载时，给宿主应用程序一个控制的机会。如果没有提供WebViewClient，默认情况下，
     * WebView将要求Activity Manager为URL选择合适的处理程序。如果提供了WebViewClient，返回true会导致当前WebView
     * 中止加载URL，而返回false会导致WebView继续像往常一样加载URL。
     * 注意:不要用请求的URL调用WebView.loadUrl(String)，然后返回true。这不必要地取消当前加载，
     * 并使用相同的URL开始新的加载。继续加载给定URL的正确方法是简单地返回false，而不调用WebView.loadUrl(String)。
     * 注意:POST请求不会调用此方法。
     * 注意:此方法可用于子帧和非http (S)方案;使用这样的URL调用WebView.loadUrl(String)将失败。
     * 参数:
     * view -初始化回调的WebView。
     * request -包含请求细节的对象。
     * 返回:
     * True表示取消当前加载，否则返回false。
     */
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        Log.i("xd===", "shouldOverrideUrlLoading");
        return super.shouldOverrideUrlLoading(view, request);
    }

    /**
     * (开始加载)
     * 通知主机应用程序页面已经开始加载。此方法在每次加载主框架时调用一次，
     * 因此带有iframe或框架集的页面将为主框架调用一次onPageStarted。这也意味着onPageStarted将不会被调用，
     * 当一个嵌入框架的内容改变，即点击一个链接，其目标是一个iframe，它也不会被调用片段导航(导航到#fragment_id)。
     * 参数:
     * view -初始化回调的WebView。
     * url -要加载的url。
     * favicon -如果该页已经存在于数据库中，则为该页的图标。
     */
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        Log.i("xd===", url + "onPageStarted");

    }

    /**
     * (加载完成)
     * 通知主机应用程序页面已完成加载。此方法仅对主框架调用。
     * 接收onPageFinished()回调并不能保证WebView绘制的下一帧将反映DOM此时的状态。
     * 为了获得当前DOM状态准备好呈现的通知，请使用WebView请求一个可视状态回调。
     * postVisualStateCallback并等待所提供的回调被触发。
     * 参数:
     * view -初始化回调的WebView。
     * url -页面的url。
     */
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        Log.i("xd===", url + "onPageFinished");

    }

    /**
     * 通知宿主应用程序，WebView将加载由给定url指定的资源。
     * 参数:
     * view -初始化回调的WebView。
     * url - WebView将加载的资源的url。
     */
    @Override
    public void onLoadResource(WebView view, String url) {
        super.onLoadResource(view, url);
    }

    /**
     * 通知宿主应用程序，不再绘制以前页面导航中留下的WebView内容。
     * 这个回调可以用来确定在什么时候可以安全地使回收的WebView可见，以确保不显示过时的内容。
     * 它被调用在最早的点，在它可以保证WebView。onDraw将不再从以前的导航中绘制任何内容。
     * 下一次绘制将显示WebView的背景色，或者显示新加载页面的一些内容。
     * 此方法在HTTP响应体开始加载时调用，在DOM中反映，并将在后续绘制中可见。这个回调发生在文档加载过程的早期，
     * 因此您应该预料到链接的资源(例如CSS和图像)可能不可用。
     * 有关可视状态更新的更细粒度通知，请参阅WebView.postVisualStateCallback。
     * 请注意，所有条件和建议都适用于WebView。postVisualStateCallback也适用于这个API。
     * 这个回调只在主框导航时调用。
     * 参数:
     * view -发生导航的WebView。
     * url -与触发此回调的页面导航相对应的url。
     */
    @Override
    public void onPageCommitVisible(WebView view, String url) {
        super.onPageCommitVisible(view, url);
    }

    /**
     * 将资源请求通知主机应用程序，并允许应用程序返回数据。如果返回值为空，WebView将继续像往常一样加载资源。
     * 否则，将使用返回的响应和数据。
     * 此回调可用于各种URL方案(例如，http(s):、data:、file:等)，而不仅仅是那些通过网络发送请求的方案。
     * javascript: URLs, blob: URLs，或者通过file:///android_asset/或file:// android_res/ URLs访问的资源都不会调用这个函数。
     * 在重定向的情况下，这只对初始资源URL调用，而不对任何后续重定向URL调用。
     * 注意:这个方法是在UI线程以外的线程上调用的，所以客户端在访问私有数据或视图系统时应该谨慎。
     * 注意:当启用安全浏览时，这些url仍然会接受安全浏览检查。如果不希望这样，您可以使用WebView.setSafeBrowsingWhitelist
     * 来跳过该主机的安全浏览检查，或者通过调用SafeBrowsingResponse.proceed来消除onSafeBrowsingHit中的警告。
     * 参数:
     * view -请求资源的WebView。
     * request -包含请求细节的对象。
     * 返回:
     * 包含响应信息的webresourcerresponse，如果WebView应该自己加载资源，则为null。
     */
    @Nullable
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return super.shouldInterceptRequest(view, request);
    }

    /**
     * (加载失败)
     * 向主机应用程序报告web资源加载错误。这些错误通常表示无法连接到服务器。请注意，
     * 与已弃用的回调版本不同，新版本将对任何资源(iframe、image等)调用，而不仅仅是对主页。
     * 因此，建议在此回调中执行所需的最少工作。
     * 参数:
     * view -初始化回调的WebView。
     * request——原始请求。
     * error -有关发生错误的信息。
     */
    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        Log.i("xd===", view.getUrl() + "onPageFinished");


    }

    /**
     * (加载证书错误网页失败)
     * 通知主机应用程序，在加载资源时从服务器接收到HTTP错误。HTTP错误状态码>= 400。
     * 这个回调将被任何资源(iframe, image等)调用，而不仅仅是主页。因此，建议在此回调中执行所需的最少工作。
     * 注意，服务器响应的内容可能不会在errorResponse参数中提供。
     * 参数:
     * view -初始化回调的WebView。
     * request——原始请求。
     * errorResponse -错误发生的信息。
     */
    @Override
    public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
        super.onReceivedHttpError(view, request, errorResponse);
    }

    /**
     * 作为主机应用程序，如果浏览器应该重新发送数据，因为请求的页面是POST的结果。默认值是不重新发送数据。
     * 参数:
     * view -初始化回调的WebView。
     * dontResend -当浏览器不应该重发时发送的消息
     * resend-当浏览器应该重发数据时发送的消息
     */
    @Override
    public void onFormResubmission(WebView view, Message dontResend, Message resend) {
        super.onFormResubmission(view, dontResend, resend);
    }

    /**
     * 通知宿主应用程序更新其访问的链接数据库。
     * 参数:
     * view -初始化回调的WebView。
     * url -被访问的url。
     * isReload -如果此url正在被重新加载，则为true。
     */
    @Override
    public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
        super.doUpdateVisitedHistory(view, url, isReload);
    }

    /**
     * 通知主机应用程序在加载资源时发生SSL错误。主机应用程序必须调用SslErrorHandler。
     * cancel或SslErrorHandler.proceed。请注意，该决策可能会被保留以用于对未来SSL错误的响应。默认行为是取消加载。
     * 此API仅在可恢复的SSL证书错误时调用。在不可恢复的错误的情况下(例如当服务器失败的客户端)，
     * WebView将调用onReceivedError(WebView, WebResourceRequest, WebResourceError)与ERROR_FAILED_SSL_HANDSHAKE。
     * 建议应用程序不要提示用户SSL错误，因为用户不太可能做出明智的安全决策，而且WebView没有提供任何UI以有意义的方式
     * 显示错误的详细信息。此方法的应用程序重写可能会显示自定义错误页面或静默记录问题，
     * 但强烈建议始终调用SslErrorHandler。取消并且不允许继续过去的错误。
     * 参数:
     * view -初始化回调的WebView。
     * handler——一个SslErrorHandler，用来处理用户的响应。
     * error - SSL错误对象。
     */
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        super.onReceivedSslError(view, handler, error);
    }

    /**
     * 通知主机应用程序处理SSL客户机证书请求。如果需要，主机应用程序负责显示UI并提供密钥。
     * 有三种响应方式:继续,ClientCertRequest。cancel，或者clientcertrerequest .ignore。
     * 如果ClientCertRequest, Webview将响应存储在内存中(在应用程序的生命周期内)。
     * proceed或ClientCertRequest。cancel被调用，并且不会为相同的主机和端口对再次调用onReceivedClientCertRequest()。
     * Webview不存储ClientCertRequest的响应。Ignore被调用。请注意，chromium网络堆栈中的多个层可能会缓存响应，因此ignore的行为只是最好的情况。
     * 这个方法在UI线程上被调用。在回调期间，连接被挂起。对于大多数用例，应用程序应该实现android.security.KeyChainAliasCallback接口，
     * 并将其传递给android.security.KeyChain.choosePrivateKeyAlias来启动一个活动，以便用户选择合适的别名。
     * keychain活动将通过实现接口中的回调方法提供别名。接下来，应用程序应该创建一个异步任务来调用android.security.KeyChain.getPrivateKey来接收密钥。
     * 客户端证书的一个示例实现可以在AOSP浏览器中看到。默认行为是取消，不返回客户端证书。
     * 参数:
     * view -发起回调请求的WebView
     * request-一个ClientCertRequest的实例
     */
    @Override
    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
        super.onReceivedClientCertRequest(view, request);
    }

    /**
     * 通知主机应用程序WebView收到了HTTP身份验证请求。主机应用程序可以使用提供的HttpAuthHandler
     * 来设置WebView对请求的响应。默认行为是取消请求。
     * 注意:提供的HttpAuthHandler必须在UI线程上使用。
     * 参数:
     * view——正在初始化回调处理程序的WebView
     * ——HttpAuthHandler用于设置WebView的响应主机
     * ——host需要身份验证域的主机
     * ——realm需要身份验证的域
     * 参见:
     * WebView.getHttpAuthUsernamePassword
     */
    @Override
    public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
        super.onReceivedHttpAuthRequest(view, handler, host, realm);
    }

    /**
     * 给宿主应用程序一个同步处理键事件的机会。例如，菜单快捷键事件需要这样过滤。
     * 如果返回true, WebView将不处理键事件。如果返回false, WebView将始终处理key事件，
     * 因此视图链中的任何super都不会看到key事件。默认行为返回false。
     * 参数:
     * view -初始化回调的WebView。event -关键事件。
     * 返回:
     * 如果主机应用程序希望自己处理键事件，则返回True，否则返回false
     */
    @Override
    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
        return super.shouldOverrideKeyEvent(view, event);
    }

    /**
     * 通知主机应用程序一个键没有被WebView处理。除了系统键，WebView总是在正常流中消耗键，
     * 或者如果shouldOverrideKeyEvent返回true。这是从分派键的位置异步调用的。
     * 它使主机应用程序有机会处理未处理的键事件。
     * 参数:
     * view -初始化回调的WebView。
     * event -关键事件。
     */
    @Override
    public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
        super.onUnhandledKeyEvent(view, event);
    }

    /**
     * 通知主机应用程序应用于WebView的比例已经改变。
     * 参数:
     * view -初始化回调的WebView。oldScale -旧的比例因子newScale -新的比例因子
     */
    @Override
    public void onScaleChanged(WebView view, float oldScale, float newScale) {
        super.onScaleChanged(view, oldScale, newScale);
    }

    /**
     * 通知主机应用程序自动登录用户的请求已被处理。
     * 参数:
     * view -请求登录的WebView。
     * realm -用于查找帐户的帐户领域。
     * account—可选帐户。如果不为空，则应对照设备上的帐户进行检查。如果它是一个有效的帐户，则应该使用它来登录用户。
     * args -用于登录用户的特定于验证器的参数。
     */
    @Override
    public void onReceivedLoginRequest(WebView view, String realm, @Nullable String account, String args) {
        super.onReceivedLoginRequest(view, realm, account, args);
    }

    /**
     * 通知宿主应用程序，给定的WebView的呈现进程已经退出。多个WebView实例可能与单个呈现进程相关联;
     * onRenderProcessGone将被调用每个WebView的影响。这个回调的应用程序实现应该只尝试清理作为参数给出的特定WebView，
     * 而不应该假设其他WebView实例受到影响。给定的WebView不能使用，应该从视图层次结构中删除，所有对它的引用都应该清理，
     * 例如，Activity或其他类中的任何引用都使用android.view.View.findViewById和类似的调用等保存。为了使渲染过程崩溃，
     * 应用程序可以在WebView上调用loadUrl("chrome://crash")。注意，如果多个WebView实例共享一个渲染进程，
     * 它们可能会受到影响，而不仅仅是加载chrome://crash的特定WebView。
     * 参数:
     * view -需要清理的WebView。细节——它退出的原因。
     * 返回:
     * 如果主机应用程序处理进程退出的情况，则为True，否则，如果呈现进程崩溃，则应用程序崩溃，如果呈现进程被系统杀死，
     * 则应用程序被杀死。
     */
    @Override
    public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
        return super.onRenderProcessGone(view, detail);
    }

    /**
     * 通知主机应用程序一个加载URL已被安全浏览标记。应用程序必须调用回调来指示首选响应。默认行为是向用户显示插页广告，
     * 并显示报告复选框。如果应用程序需要显示自己的自定义插页式UI，则可以使用SafeBrowsingResponse异步调用回调。
     * backToSafety或SafeBrowsingResponse。继续，取决于用户的响应。
     * 参数:
     * view -命中恶意资源的WebView。
     * request -包含请求细节的对象。
     * threatType -资源被安全浏览捕获的原因，对应于SAFE_BROWSING_THREAT_*值。
     * callback——应用程序必须调用其中一个回调方法。
     */
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType, SafeBrowsingResponse callback) {
        super.onSafeBrowsingHit(view, request, threatType, callback);
    }
}
